package com.hwtx.form.domain.handle;

import com.hwtx.form.annotation.Action;
import com.hwtx.form.annotation.FormType;
import com.hwtx.form.annotation.Log;
import com.hwtx.form.annotation.OperationType;
import com.hwtx.form.domain.def.FormDef;
import com.hwtx.form.domain.listener.ResourceChangeEvent;
import com.hwtx.form.domain.repo.SysRoleService;
import com.hwtx.form.domain.service.RacService;
import com.hwtx.form.domain.service.ResourceService;
import com.hwtx.form.domain.vo.FormData;
import com.hwtx.form.domain.vo.FormRepData;
import com.hwtx.form.query.FormValueQuery;
import io.geekidea.boot.system.dto.RoleMenusDto;
import io.geekidea.boot.system.dto.SysRoleDto;
import io.geekidea.boot.system.vo.SysRoleVo;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.context.event.EventListener;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.hwtx.form.domain.FormConstants.RESOURCE_NAME_PREFIX;
import static com.hwtx.form.domain.FormConstants.ROLE_FORM_HANDLE_NAME;
import static com.hwtx.form.util.JacksonUtil.map2Oject;

@FormType(ROLE_FORM_HANDLE_NAME)
@Slf4j
public class RoleFormDataHandle implements FormDataHandle {

    @Resource
    SysRoleService sysRoleService;
    @Resource
    RacService racService;
    @Resource
    private ResourceService resourceService;

    @Override
    public FormRepData getFormData(FormDef formDef, FormValueQuery formValueQuery) {
        SysRoleVo sysRoleVo = sysRoleService.getSysRoleById(formValueQuery.getValueIds().getFirst());
        return FormRepData.builder().data(BeanMap.create(sysRoleVo)).build();
    }

    @EventListener
    public void dataModelChange(ResourceChangeEvent event) {
        log.info("RoleFormDataHandle resourceChange event, resourceId = {}", event.getResourceId());
        resourceService.deleteResMenuRel(List.of(event.getResourceId()));
    }

    @Override
    public Object saveFormData(FormDef formDef, FormData formData) {
        SysRoleDto sysRoleDto = map2Oject(formData.getData(), SysRoleDto.class);
        assert sysRoleDto != null;
        if (sysRoleDto.getId() == null) {
            return sysRoleService.addSysRole(sysRoleDto);
        } else {
            return sysRoleService.updateSysRole(sysRoleDto);
        }
    }

    @Override
    public Object removeFormData(FormDef formDef, FormValueQuery formValueQuery) {
        if (CollectionUtils.isNotEmpty(formValueQuery.getValueIds())) {
            return sysRoleService.deleteSysRole(formValueQuery.getValueIds().getFirst());
        }
        return false;
    }

    @Action
    @Log(type = OperationType.UPDATE, value = "更新角色资源")
    public boolean updateResource(Map<String, Object> formData) {
        String resourceIds = (String) formData.get("resourceIds");
        String roleId = (String) formData.get("roleId");
        if (roleId == null) {
            throw new RuntimeException("roleId不能为空");
        }
        if (resourceIds == null) {
            throw new RuntimeException("资源列表不能为空");
        }
        if (isSystemRole(Long.valueOf(roleId))) {
            throw new UnsupportedOperationException("系统角色无需修改资源");
        }

        RoleMenusDto roleMenusDto = new RoleMenusDto();
        roleMenusDto.setRoleId(Long.valueOf(roleId));
        roleMenusDto.setMenuIds(Arrays.stream(resourceIds.split(",")).map(Long::valueOf).collect(Collectors.toList()));
        return racService.setRoleMenus(roleMenusDto);
    }

    @Action
    @Log(type = OperationType.UPDATE, value = "批量更新角色资源")
    public boolean updateResources(Map<String, Object> formData) {
        formData.entrySet().stream().filter(entry -> entry.getKey().startsWith(RESOURCE_NAME_PREFIX))
                .forEach(entry -> {
                    String roleId = entry.getKey().substring(RESOURCE_NAME_PREFIX.length());
                    if (StringUtils.isEmpty(roleId)) {
                        throw new RuntimeException("角色id不能为空");
                    }
                    if (isSystemRole(Long.valueOf(roleId))) {
                        log.info("系统角色无需修改资源,role = {}", roleId);
                        return;
                    }
                    String resourceName = (String) entry.getValue();
                    if (resourceName == null) {
                        throw new RuntimeException("资源名称不能为空");
                    }
                    RoleMenusDto roleMenusDto = new RoleMenusDto();
                    roleMenusDto.setRoleId(Long.valueOf(roleId));
                    roleMenusDto.setMenuIds(Arrays.stream(resourceName.split(",")).map(Long::valueOf).collect(Collectors.toList()));
                    racService.setRoleMenus(roleMenusDto);
                });
        return true;
    }

    private boolean isSystemRole(Long roleId) {
        SysRoleVo sysRoleVo = sysRoleService.getSysRoleById(roleId);
        if (sysRoleVo == null) {
            throw new RuntimeException("角色不存在");
        }
        return BooleanUtils.isTrue(sysRoleVo.getIsSystem());
    }
}
